package org.example.clouddemo.service.common.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.catalina.security.SecurityUtil;
import org.example.clouddemo.bean.common.dto.ProductDTO;
import org.example.clouddemo.bean.common.entity.Product;
import org.example.clouddemo.bean.common.entity.Stock;
import org.example.clouddemo.bean.common.param.UpdateProductParam;
import org.example.clouddemo.bean.common.vo.ProductVO;
import org.example.clouddemo.service.common.mapper.ProductMapper;
import org.example.clouddemo.service.common.ProductService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.example.clouddemo.service.common.mapper.StockMapper;
import org.example.common.exception.AppRunTimeException;
import org.example.common.utils.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;


/**
* <p>
* 产品表 服务实现类
* </p>
*
* @author hzg
* @since 2025-06-07
*/
@Service
public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> implements ProductService {

    @Autowired
    private ProductMapper productMapper;

    @Autowired
    private StockServiceImpl stockService;

    @Autowired
    private StockMapper stockMapper;
    @Value("${file-save-path}")
    private String fileSavePath;

    private SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy/MM/dd/");

    @Override
    public IPage<ProductVO> selectPageVo(Page page) {
        QueryWrapper<Product> queryWrapper = new QueryWrapper<>();
        if(SecurityUtils.USER_TYPE_HEADER.equals("app")){
            queryWrapper.lambda().eq(Product::getEnableFlag, true);
        }
        queryWrapper.orderByDesc("create_time");
        Page<Product> pageRes = productMapper.selectPage(page, queryWrapper);
        // 将 Product 转换为 ProductVO
        List<ProductVO> voList = pageRes.getRecords().stream().map(product -> {
            ProductVO productVO = BeanUtil.copyProperties(product, ProductVO.class);

            // 查询库存
            QueryWrapper<Stock> stockQueryWrapper = new QueryWrapper<>();
            stockQueryWrapper.lambda().eq(Stock::getProductId, product.getId());
            Stock stock = stockMapper.selectOne(stockQueryWrapper);

            // 设置库存数量
            if (stock != null) {
                productVO.setStock(stock.getQuantity());
            } else {
                productVO.setStock(0); // 默认值
            }

            return productVO;
        }).collect(Collectors.toList());
        // 构建新的 VO 分页对象
        Page<ProductVO> voPage = new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
        voPage.setRecords(voList);

        return voPage;
    }


    @Override
    public Product selectOne(Product product) {
        QueryWrapper<Product> queryWrapper = new QueryWrapper<>(product);
        return productMapper.selectOne(queryWrapper);
    }

    @Override
    public int create(ProductDTO productDTO, MultipartFile file, HttpServletRequest request) {
        String url = getUrl(file, request);
        Product product = BeanUtil.copyProperties(productDTO, Product.class);
        product.setProductImg(url);
        productMapper.insert(product);
        Product productIn = productMapper.selectOne(new QueryWrapper<>(product));
        Stock stock = new Stock();
        stock.setProductId(productIn.getId());
        stock.setQuantity(productDTO.getStock());
        return stockMapper.insert(stock);

    }

    @Override
    public int update(UpdateProductParam param, MultipartFile file, HttpServletRequest request) {
        Integer stock = param.getStock();
        if (stock != null && stock!=0){
            Stock stockIn = stockMapper.selectOne(new QueryWrapper<Stock>().eq("product_id", param.getId()));
            stockIn.setQuantity(stock);
            stockMapper.updateById(stockIn);
        }
        Product product = BeanUtil.copyProperties(param, Product.class);
        if(file != null){
            String url = getUrl(file, request);
            product.setProductImg(url);
        }

        return productMapper.updateById(product);
    }

    @Override
    public int delete(String id, boolean flag) {
        QueryWrapper<Product> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(Product::getId, id);
        Product product = new Product();
        product.setEnableFlag(flag);
        product.setId(Long.parseLong(id));
        return productMapper.updateById(product);
    }


    @Override
    public List<ProductVO> recommendProducts(Long productId) {
        Product product = productMapper.selectById(productId);
        if (product == null) {
            return Collections.emptyList();
        }

        // 构建查询条件
        QueryWrapper<Product> queryWrapper = new QueryWrapper<>();

        // 1. 同分类的产品
        if (product.getCategory() != null && !product.getCategory().isEmpty()) {
            queryWrapper.eq("category", product.getCategory());
        }

        // 2. 价格相近的产品 (±20%)
        BigDecimal lowerPrice = product.getPrice().multiply(new BigDecimal("0.8"));
        BigDecimal upperPrice = product.getPrice().multiply(new BigDecimal("1.2"));
        queryWrapper.between("price", lowerPrice, upperPrice);

        // 3. 时间相近的产品 (近3个月内)
        LocalDateTime timeThreshold = product.getCreateTime().minusMonths(3);
        queryWrapper.ge("create_time", timeThreshold);

        // 4. 排除当前产品
        queryWrapper.ne("id", productId);

        // 5. 只查询启用的产品
        queryWrapper.eq("enable_flag", true);

        // 6. 排序：先按分类，再按价格接近度，最后按创建时间
        queryWrapper.orderByDesc("category")
                .orderByAsc("ABS(price - " + product.getPrice() + ")")
                .orderByAsc("sort_index")
                .orderByDesc("create_time");

        // 限制返回数量
        queryWrapper.last("LIMIT 10");

        List<Product> products = productMapper.selectList(queryWrapper);
        List<ProductVO> collect = products.stream().map(productByRecommend -> {
                    ProductVO productVO = BeanUtil.copyProperties(productByRecommend, ProductVO.class);
                    // 查询库存
                    QueryWrapper<Stock> stockQueryWrapper = new QueryWrapper<>();
                    stockQueryWrapper.lambda().eq(Stock::getProductId, productByRecommend.getId());
                    Stock stock = stockMapper.selectOne(stockQueryWrapper);

                    // 设置库存数量
                    if (stock != null) {
                        productVO.setStock(stock.getQuantity());
                    } else {
                        productVO.setStock(0); // 默认值
                    }
                    return productVO;
                }).filter(productVO -> productVO.getStock() > 0)
                .collect(Collectors.toList());
        return collect;

    }

    private String getUrl(MultipartFile file, HttpServletRequest request) {
        String directory = simpleDateFormat.format(new Date());
        /**
         * 文件保存目录 D:/images/
         * 如果目录不存在，则创建
         */
        File dir = new File(fileSavePath + directory);
        if (!dir.exists()) {
            dir.mkdirs();
        }
        System.out.println("图片上传，保存的位置:" + fileSavePath + directory);

        /**
         * 给文件重新设置一个名字
         * 后缀
         */
        String suffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
        String newFileName = UUID.randomUUID().toString().replaceAll("-", "") + suffix;

        //4.创建这个新文件
        File newFile = new File(fileSavePath + directory + newFileName);
        //5.复制操作
        try {
            file.transferTo(newFile);
            //协议 :// ip地址 ：端口号 / 文件目录(/images/xxx.jpg)
            String url = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + "/images/" + directory + newFileName;
            System.out.println("文件上传，访问URL：" + url);
            return url;
        }catch (IOException e){
            throw new AppRunTimeException("文件上传失败");
        }
    }
}
